home *** CD-ROM | disk | FTP | other *** search
/ Oh!X 2000 Spring / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).7z / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).bin / DXF / samples / multimedia / dplay / src / duel / dsutil.cpp < prev    next >
C/C++ Source or Header  |  1999-07-14  |  13KB  |  466 lines

  1. //-----------------------------------------------------------------------------
  2. // File: dsutil.cpp
  3. //
  4. // Desc: Routines for dealing with sounds from resources
  5. //
  6. // Copyright (C) 1995-1999 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #include <windows.h>
  9. #include <mmsystem.h>
  10. #include <dsound.h>
  11. #include "dsutil.h"
  12.  
  13.  
  14. //-----------------------------------------------------------------------------
  15. // Globals
  16. //-----------------------------------------------------------------------------
  17. LPDIRECTSOUND g_pDS = NULL;
  18.  
  19.  
  20.  
  21.  
  22. //-----------------------------------------------------------------------------
  23. // Name: DSUtil_LoadSoundBuffer()
  24. // Desc:
  25. //-----------------------------------------------------------------------------
  26. LPDIRECTSOUNDBUFFER DSUtil_LoadSoundBuffer( LPDIRECTSOUND pDS, LPCTSTR strName )
  27. {
  28.     LPDIRECTSOUNDBUFFER pDSB = NULL;
  29.     DSBUFFERDESC        dsbd;
  30.     BYTE*               pbWaveData;
  31.  
  32.     ZeroMemory( &dsbd, sizeof(dsbd) );
  33.     dsbd.dwSize  = sizeof(dsbd);
  34.     dsbd.dwFlags = DSBCAPS_STATIC|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|
  35.                    DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPOSITIONNOTIFY;
  36.  
  37.     if( SUCCEEDED( DSUtil_GetWaveResource( NULL, strName, &dsbd.lpwfxFormat,
  38.                                            &pbWaveData, &dsbd.dwBufferBytes ) ) )
  39.     {
  40.  
  41.         if( SUCCEEDED( pDS->CreateSoundBuffer( &dsbd, &pDSB, NULL ) ) )
  42.         {
  43.             if( FAILED( DSUtil_FillSoundBuffer( pDSB, pbWaveData,
  44.                                                 dsbd.dwBufferBytes ) ) )
  45.             {
  46.                 pDSB->Release();
  47.                 pDSB = NULL;
  48.             }
  49.         }
  50.         else
  51.         {
  52.             pDSB = NULL;
  53.         }
  54.     }
  55.  
  56.     return pDSB;
  57. }
  58.  
  59.  
  60.  
  61.  
  62. //-----------------------------------------------------------------------------
  63. // Name: DSUtil_ReloadSoundBuffer()
  64. // Desc: 
  65. //-----------------------------------------------------------------------------
  66. HRESULT DSUtil_ReloadSoundBuffer( LPDIRECTSOUNDBUFFER pDSB, LPCTSTR strName )
  67. {
  68.     BYTE* pbWaveData;
  69.     DWORD cbWaveSize;
  70.  
  71.     if( FAILED( DSUtil_GetWaveResource( NULL, strName, NULL, &pbWaveData,
  72.                                         &cbWaveSize ) ) )
  73.         return E_FAIL;
  74.  
  75.     if( FAILED( pDSB->Restore() ) )
  76.         return E_FAIL;
  77.  
  78.     if( FAILED( DSUtil_FillSoundBuffer( pDSB, pbWaveData, cbWaveSize ) ) )
  79.         return E_FAIL;
  80.  
  81.     return S_OK;
  82. }
  83.  
  84.  
  85.  
  86.  
  87. //-----------------------------------------------------------------------------
  88. // Name: 
  89. // Desc: 
  90. //-----------------------------------------------------------------------------
  91. HRESULT DSUtil_GetWaveResource( HMODULE hModule, LPCTSTR strName,
  92.                                 WAVEFORMATEX** ppWaveHeader, BYTE** ppbWaveData,
  93.                                 DWORD* pcbWaveSize )
  94. {
  95.     HRSRC   hResInfo;
  96.     HGLOBAL hResData;
  97.     VOID*   pvRes;
  98.  
  99.     if( NULL == ( hResInfo = FindResource( hModule, strName, TEXT("WAVE") ) ) )
  100.     {
  101.         if( NULL == ( hResInfo = FindResource( hModule, strName, TEXT("WAV") ) ) )
  102.             return E_FAIL;
  103.     }
  104.  
  105.     if( NULL == ( hResData = LoadResource( hModule, hResInfo ) ) )
  106.         return E_FAIL;
  107.  
  108.     if( NULL == ( pvRes = LockResource( hResData ) ) )
  109.         return E_FAIL;
  110.  
  111.     if( FAILED( DSUtil_ParseWaveResource( pvRes, ppWaveHeader, ppbWaveData,
  112.                                           pcbWaveSize ) ) )
  113.         return E_FAIL;
  114.  
  115.     return S_OK;
  116. }
  117.  
  118.  
  119.  
  120.  
  121. //-----------------------------------------------------------------------------
  122. // Name: 
  123. // Desc: 
  124. //-----------------------------------------------------------------------------
  125. SoundObject* DSUtil_CreateSound( LPCTSTR strName, DWORD dwNumConcurrentBuffers )
  126. {
  127.     SoundObject*   pSound = NULL;
  128.     LPWAVEFORMATEX pWaveHeader;
  129.     BYTE*          pbData;
  130.     DWORD          cbData;
  131.  
  132.     if( NULL == g_pDS )
  133.         return NULL;
  134.  
  135.     if( dwNumConcurrentBuffers < 1 )
  136.         dwNumConcurrentBuffers = 1;
  137.  
  138.     if( SUCCEEDED( DSUtil_GetWaveResource( NULL, strName, &pWaveHeader,
  139.                                            &pbData, &cbData ) ) )
  140.     {
  141.         pSound = new SoundObject;
  142.         pSound->dwNumBuffers = dwNumConcurrentBuffers;
  143.         pSound->pbWaveData   = pbData;
  144.         pSound->cbWaveSize   = cbData;
  145.         pSound->dwCurrent    = 0;
  146.         pSound->pdsbBuffers  = new LPDIRECTSOUNDBUFFER[dwNumConcurrentBuffers+1];
  147.  
  148.         pSound->pdsbBuffers[0] = DSUtil_LoadSoundBuffer( g_pDS, strName );
  149.  
  150.         for( DWORD i=1; i<pSound->dwNumBuffers; i++ )
  151.         {
  152.             if( FAILED( g_pDS->DuplicateSoundBuffer( pSound->pdsbBuffers[0],
  153.                                                    &pSound->pdsbBuffers[i] ) ) )
  154.             {
  155.                 pSound->pdsbBuffers[i] = DSUtil_LoadSoundBuffer( g_pDS, strName );
  156.                 if( NULL == pSound->pdsbBuffers[i] )
  157.                 {
  158.                     DSUtil_DestroySound( pSound );
  159.                     pSound = NULL;
  160.                     break;
  161.                 }
  162.             }
  163.         }
  164.     }
  165.  
  166.     return pSound;
  167. }
  168.  
  169.  
  170.  
  171.  
  172. //-----------------------------------------------------------------------------
  173. // Name: DSUtil_DestroySound()
  174. // Desc: 
  175. //-----------------------------------------------------------------------------
  176. VOID DSUtil_DestroySound( SoundObject* pSound )
  177. {
  178.     if( pSound )
  179.     {
  180.         for( DWORD i=0; i<pSound->dwNumBuffers; i++ )
  181.         {
  182.             if( pSound->pdsbBuffers[i] )
  183.                 pSound->pdsbBuffers[i]->Release();
  184.         }
  185.         
  186.         delete pSound->pdsbBuffers;
  187.         delete pSound;
  188.     }
  189. }
  190.  
  191.  
  192.  
  193.  
  194. //-----------------------------------------------------------------------------
  195. // Name: 
  196. // Desc: 
  197. //-----------------------------------------------------------------------------
  198. LPDIRECTSOUNDBUFFER DSUtil_GetFreeSoundBuffer( SoundObject* pSound )
  199. {
  200.     HRESULT hr;
  201.     DWORD   dwStatus;
  202.  
  203.     if( NULL == pSound )
  204.         return NULL;
  205.  
  206.     LPDIRECTSOUNDBUFFER pDSB = pSound->pdsbBuffers[pSound->dwCurrent];
  207.     if( NULL == pDSB )
  208.         return NULL;
  209.  
  210.     hr = pDSB->GetStatus( &dwStatus );
  211.     if( FAILED(hr) )
  212.         dwStatus = 0;
  213.  
  214.     if( dwStatus & DSBSTATUS_PLAYING )
  215.     {
  216.         if( pSound->dwNumBuffers <= 1 )
  217.             return NULL;
  218.  
  219.         if( ++pSound->dwCurrent >= pSound->dwNumBuffers )
  220.             pSound->dwCurrent = 0;
  221.  
  222.         pDSB = pSound->pdsbBuffers[pSound->dwCurrent];
  223.         
  224.         hr = pDSB->GetStatus( &dwStatus);
  225.         if( FAILED(hr) )
  226.             dwStatus = 0;
  227.  
  228.         if( dwStatus & DSBSTATUS_PLAYING )
  229.         {
  230.             pDSB->Stop();
  231.             pDSB->SetCurrentPosition( 0 );
  232.         }
  233.     }
  234.  
  235.     if( dwStatus & DSBSTATUS_BUFFERLOST )
  236.     {
  237.         if( FAILED( pDSB->Restore() ) )
  238.             return NULL;
  239.             
  240.         if( FAILED( DSUtil_FillSoundBuffer( pDSB, pSound->pbWaveData,
  241.                                             pSound->cbWaveSize ) ) )
  242.             return NULL;
  243.     }
  244.  
  245.     return pDSB;
  246. }
  247.  
  248.  
  249.  
  250.  
  251. //-----------------------------------------------------------------------------
  252. // Name: DSUtil_PlaySound()
  253. // Desc: 
  254. //-----------------------------------------------------------------------------
  255. HRESULT DSUtil_PlaySound( SoundObject* pSound, DWORD dwPlayFlags )
  256. {
  257.     if( NULL == pSound )
  258.         return E_FAIL;
  259.  
  260.     if( !(dwPlayFlags & DSBPLAY_LOOPING) || (pSound->dwNumBuffers == 1) )
  261.     {
  262.         LPDIRECTSOUNDBUFFER pDSB = DSUtil_GetFreeSoundBuffer( pSound );
  263.         if( pDSB )
  264.         {
  265.             if( SUCCEEDED( pDSB->Play( 0, 0, dwPlayFlags ) ) )
  266.                 return S_OK;
  267.         }
  268.     }
  269.  
  270.     return E_FAIL;
  271. }
  272.  
  273.  
  274.  
  275.  
  276. //-----------------------------------------------------------------------------
  277. // Name: DSUtil_StopSound()
  278. // Desc: 
  279. //-----------------------------------------------------------------------------
  280. HRESULT DSUtil_StopSound( SoundObject* pSound )
  281. {
  282.     if( NULL == pSound )
  283.         return E_FAIL;
  284.  
  285.     for( DWORD i=0; i<pSound->dwNumBuffers; i++ )
  286.     {
  287.         pSound->pdsbBuffers[i]->Stop();
  288.         pSound->pdsbBuffers[i]->SetCurrentPosition( 0 );
  289.     }
  290.  
  291.     return S_OK;
  292. }
  293.  
  294.  
  295.  
  296.  
  297. //-----------------------------------------------------------------------------
  298. // Name: 
  299. // Desc: 
  300. //-----------------------------------------------------------------------------
  301. HRESULT DSUtil_FillSoundBuffer( LPDIRECTSOUNDBUFFER pDSB, BYTE* pbWaveData,
  302.                                 DWORD dwWaveSize )
  303. {
  304.     VOID* pMem1;
  305.     VOID* pMem2;
  306.     DWORD dwSize1;
  307.     DWORD dwSize2;
  308.  
  309.     if( NULL == pDSB || NULL == pbWaveData || 0 == dwWaveSize )
  310.         return E_FAIL;
  311.  
  312.     if( FAILED( pDSB->Lock( 0, dwWaveSize, &pMem1, &dwSize1, &pMem2,
  313.                             &dwSize2, 0 ) ) )
  314.         return E_FAIL;
  315.  
  316.     if( 0 != dwSize1 ) CopyMemory( pMem1, pbWaveData, dwSize1 );
  317.     if( 0 != dwSize2 ) CopyMemory( pMem2, pbWaveData+dwSize1, dwSize2 );
  318.  
  319.     pDSB->Unlock( pMem1, dwSize1, pMem2, dwSize2);
  320.  
  321.     return S_OK;
  322. }
  323.  
  324.  
  325.  
  326.  
  327. //-----------------------------------------------------------------------------
  328. // Name: 
  329. // Desc: 
  330. //-----------------------------------------------------------------------------
  331. HRESULT DSUtil_ParseWaveResource( VOID* pvRes, WAVEFORMATEX** ppWaveHeader,
  332.                                   BYTE** ppbWaveData, DWORD* pcbWaveSize )
  333. {
  334.     DWORD* pdw;
  335.     DWORD* pdwEnd;
  336.     DWORD  dwRiff;
  337.     DWORD  dwType;
  338.     DWORD  dwLength;
  339.  
  340.     if( ppWaveHeader )
  341.         *ppWaveHeader = NULL;
  342.  
  343.     if( ppbWaveData )
  344.         *ppbWaveData = NULL;
  345.  
  346.     if( pcbWaveSize )
  347.         *pcbWaveSize = 0;
  348.  
  349.     pdw      = (DWORD*)pvRes;
  350.     dwRiff   = *pdw++;
  351.     dwLength = *pdw++;
  352.     dwType   = *pdw++;
  353.  
  354.     if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') )
  355.         return E_FAIL;
  356.  
  357.     if( dwType != mmioFOURCC('W', 'A', 'V', 'E') )
  358.         return E_FAIL;
  359.  
  360.     pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
  361.  
  362.     while( pdw < pdwEnd )
  363.     {
  364.         dwType   = *pdw++;
  365.         dwLength = *pdw++;
  366.  
  367.         if( dwType == mmioFOURCC('f', 'm', 't', ' ') )
  368.         {
  369.             if (ppWaveHeader && !*ppWaveHeader)
  370.             {
  371.                 if( dwLength < sizeof(WAVEFORMAT) )
  372.                     return E_FAIL;
  373.  
  374.                 *ppWaveHeader = (WAVEFORMATEX*)pdw;
  375.  
  376.                 if( (!ppbWaveData || *ppbWaveData) &&
  377.                     (!pcbWaveSize || *pcbWaveSize) )
  378.                 {
  379.                     return S_OK;
  380.                 }
  381.             }
  382.         }
  383.  
  384.         if( dwType == mmioFOURCC('d', 'a', 't', 'a') )
  385.         {
  386.             if( (ppbWaveData && !*ppbWaveData) ||
  387.                 (pcbWaveSize && !*pcbWaveSize) )
  388.             {
  389.                 if( ppbWaveData )
  390.                     *ppbWaveData = (BYTE*)pdw;
  391.  
  392.                 if( pcbWaveSize )
  393.                     *pcbWaveSize = dwLength;
  394.  
  395.                 if( !ppWaveHeader || *ppWaveHeader )
  396.                     return S_OK;
  397.             }
  398.         }
  399.  
  400.         pdw = (DWORD*)( (BYTE*)pdw + ((dwLength+1)&~1) );
  401.     }
  402.  
  403.     return E_FAIL;
  404. }
  405.  
  406.  
  407.  
  408.  
  409.  
  410. //-----------------------------------------------------------------------------
  411. // Name: DSUtil_PlayPannedSound()
  412. // Desc: Play a sound, but first set the panning according to where the
  413. //       object is on the screen. fScreenXPos is between -1.0f (left) and
  414. //       1.0f (right).
  415. //-----------------------------------------------------------------------------
  416. VOID DSUtil_PlayPannedSound( SoundObject* pSound, FLOAT fScreenXPos )
  417. {
  418.     LPDIRECTSOUNDBUFFER pDSB = DSUtil_GetFreeSoundBuffer( pSound );
  419.  
  420.     if( pDSB )
  421.     {
  422.         pDSB->SetPan( (LONG)( 10000L * fScreenXPos ) );
  423.         pDSB->Play( 0, 0, 0 );
  424.     }
  425. }
  426.  
  427.  
  428.  
  429.  
  430. //-----------------------------------------------------------------------------
  431. // Name: DSUtil_InitDirectSound()
  432. // Desc: 
  433. //-----------------------------------------------------------------------------
  434. HRESULT DSUtil_InitDirectSound( HWND hWnd )
  435. {
  436.     if( FAILED( DirectSoundCreate( NULL, &g_pDS, NULL ) ) )
  437.         return E_FAIL;
  438.  
  439.     if( FAILED( g_pDS->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) )
  440.     {
  441.         g_pDS->Release();
  442.         g_pDS = NULL;
  443.         return E_FAIL;
  444.     }
  445.  
  446.     return S_OK;
  447. }
  448.  
  449.  
  450.  
  451.  
  452. //-----------------------------------------------------------------------------
  453. // Name: DSUtil_FreeDirectSound()
  454. // Desc: 
  455. //-----------------------------------------------------------------------------
  456. VOID DSUtil_FreeDirectSound()
  457. {
  458.     if( g_pDS )
  459.         g_pDS->Release();
  460.     g_pDS = NULL;
  461. }
  462.  
  463.  
  464.  
  465.  
  466.